/* eslint-disable no-console */
import type { FetchContext } from 'ofetch'
import type { AsyncData } from 'nuxt/app'
import { useFetch } from 'nuxt/app'
import { useFetchOnResponse } from './status'
import type { KeysOf, PickFrom, UseFetchOptions } from '~/types/api'
import { useRepoId } from '~/composables/hooks/useRepoId'

type encodeString = string
const inDev = ['loc', 'development'].includes(import.meta.env.VITE_ENV)
const baseURL = (import.meta as any).env.VITE_API_HOST
const devPressURL = (import.meta as any).env.VITE_DEV_API_HOST

/** 处理响应数据 */
function onResponse(context: FetchContext<any>) {
  const { /* request, */ response, options } = context
  if (process.client) {
    if (options.customError /*  错误状态不处理 */|| response?.status === 200) {
      return null
    }
    else {
      useFetchOnResponse(context)
    }
  }
}

/** 输出 fetch error */
function responseError(context: FetchContext) {
  const { response, request/* , options */ } = context
  // 处理后端携带了错误码响应的数据
  let content = ''
  if (response?._data) {
    if (typeof response._data === 'string')
      content = response._data
    else if (typeof response._data === 'object')
      content = JSON.stringify(response._data)
  }
  if (inDev || process.server) {
    console.log(
      'useFetch fail',
      inDev ? '\nrequest:' : 'request:',
      request,
      inDev ? '\n' : '',
      content,
    )
  }
}

/** 聚合请求头参数 */
export function combineHeaders(headers?: object, options?: UseFetchOptions<any>) {
  const router = useRouter()
  let sourceHeaders: { 'cookie'?: string, 'Authorization'?: string, 'page-ref'?: encodeString, 'page-uri'?: encodeString, 'gitcode-utm-source'?: encodeString, 'page-title'?: encodeString, 'page-repo-id'?: string } = {}
  if (process.server) {
    sourceHeaders = usePickBy(usePick(useRequestHeaders(), ['sec-ch-ua', 'sec-ch-ua-mobile', 'sec-ch-ua-platform', 'upgrade-insecure-requests', 'user-agent', 'sec-fetch-site', 'sec-fetch-mode', 'sec-fetch-user', 'sec-fetch-dest', 'referer', 'cookie', 'x-forwarded-for', 'x-forwarded-port', 'x-forwarded-proto']), e => !!e)
  }
  else {
    if (!options?.apiType) {
      const { repoId } = toRefs(useRepoId())
      const { namespaceType } = storeToRefs(useGlobalInfoStore())

      let _repoId = ''
      if (router.currentRoute.value?.meta?.type === 'repo')
        _repoId = repoId.value

      let homePageTitle = ''
      // 首页reportTitle特殊处理
      const homeTitleConfig = { 0: '个人主页', 1: '组织主页' } as { [key: number]: string }
      if (router.currentRoute.value.name === 'homepage' && namespaceType.value > -1)
        homePageTitle = homeTitleConfig[namespaceType.value]

      const pageTitle: string = homePageTitle || router.currentRoute.value?.meta?.reportTitle as string || document.title || ''
      // 添加上报数据
      sourceHeaders['page-title'] = encodeURIComponent(pageTitle)
      sourceHeaders['page-ref'] = encodeURIComponent(cutParamsInUrl(window.page_ref || ''))
      sourceHeaders['page-uri'] = encodeURIComponent(cutParamsInUrl(window.location.href || ''))
      sourceHeaders['gitcode-utm-source'] = encodeURIComponent(getSignUtmSource() || '')
      sourceHeaders['page-repo-id'] = _repoId
    }
  }
  const authorization = process.server ? useCookie('GITCODE_ACCESS_TOKEN').value : window.localStorage.getItem('access_token')
  return ({
    ...headers,
    ...sourceHeaders,
    authorization: authorization ? `Bearer ${authorization}` : '',
  })
}

/** 接口前缀 */
const PREFIX = (import.meta as any).env.VITE_PASSPORT_PREFIX || ''
function prefix(request: string, opts: any): string {
  if ([
    '/api/v1/user/',
    '/api/v1/oauth/',
    '/api/v1/internal/messages',
    '/api/v1/follow',
  ].some((url: string) => request.includes(url))) {
    return PREFIX
  }
  else if (
    request?.includes('/api/v1/obs') && opts.method === 'get'
  ) {
    return PREFIX
  }
  else {
    return ''
  }
}

/**
 * 基于 useFetch 的封装
 * See {@link https://nuxt.com/docs/api/composables/use-fetch}
 * @since 3.0.0
 * @param request The URL to fetch
 * @param opts extends $fetch options and useAsyncData options
 * @returns custom useFetch
 */

export function useSsrFetch<DataT, ErrorT >(request: string, opts?: UseFetchOptions<DataT>): AsyncData<PickFrom<DataT, KeysOf<DataT>> | null, ErrorT | null> {
  return useFetch(prefix(request, opts) + request, {
    baseURL: (() => {
      if (opts?.apiType === 'node') {
        return ''
      }
      else if (opts?.apiType === 'devApi') {
        return devPressURL
      }
      else {
        return baseURL
      }
    })(),
    onRequest({ options }) {
      // Set the request headers
      options.headers = combineHeaders(options?.headers, options)
    },
    // Process the response data
    onResponse,
    onResponseError: responseError,
    credentials: 'include',
    ...opts,
  })
}

/**
 * 实现更便捷的get请求
 * @param request
 * @param opts
 * @returns useSsrFetch
 */
useSsrFetch.get = <DataT, ErrorT>(request: string, opts?: UseFetchOptions<DataT>): AsyncData<PickFrom<DataT, KeysOf<DataT>> | null, ErrorT | null> => {
  return useSsrFetch(prefix(request, opts) + request, {
    method: 'get',
    ...opts,
  })
}

/**
 * 实现更便捷的post请求
 * @param request
 * @param opts
 * @returns useSsrFetch
 */
useSsrFetch.post = <DataT, ErrorT>(request: string, opts?: UseFetchOptions<DataT>): AsyncData<PickFrom<DataT, KeysOf<DataT>> | null, ErrorT | null> => {
  return useSsrFetch(prefix(request, opts) + request, {
    method: 'post',
    ...opts,
  })
}
